/*
 * 
 * @Description: Drawing a clock
 *
 * @Version: v1.0.0
 * @Author: Hao(bds)
 * @Date: 2023/11/03
 * @Repository: https://gitee.com/bds123/draw_graphs
 */
 
#include <math.h>
#include "draw.h"
#include "delay.h"


// Rotate a point (x, y) around the center (xc, yc) by angle degrees
void rotate_point(int16_t x, int16_t y, int16_t xc, int16_t yc, float angle, int16_t *new_x, int16_t *new_y) 
{
    float radian = angle * (float)M_PI / 180.0f;
	
    *new_x = xc + (x - xc) * cosf(radian) - (y - yc) * sinf(radian);
    *new_y = yc + (x - xc) * sinf(radian) + (y - yc) * cosf(radian);
}

void draw_hand(int16_t xc, int16_t yc, float angle, int16_t length, color_t color) 
{
    int16_t x, y;
	
    rotate_point(xc + length, yc, xc, yc, angle, &x, &y);
	draw_line_ex(xc, yc, x, y, color, true);
	//在直线的顶点增加一个圆形线帽
	draw_fill_circle(x, y, 2, color);
}

void draw_clock_ticks(int16_t xc, int16_t yc, int16_t radius, color_t color) 
{
    for (int i = 0; i < 60; ++i) {
        // Calculate the angle for each tick
        float angle = i * 6.0;  // 360/60 = 6 degrees per tick

        // Calculate the starting point of each tick on the circle
        int16_t x1 = xc + radius * cosf(angle * (float)M_PI / 180.0f);
        int16_t y1 = yc + radius * sinf(angle * (float)M_PI / 180.0f);

        // Determine the length of the tick: longer for hour, shorter for minutes and seconds
        int16_t tick_length = (i % 5 == 0) ? 10 : 5;

        // Calculate the ending point of each tick inside the circle
        int16_t x2 = xc + (radius - tick_length) * cosf(angle * (float)M_PI / 180.0f);
        int16_t y2 = yc + (radius - tick_length) * sinf(angle * (float)M_PI / 180.0f);

        // Draw the tick
        draw_line_ex(x1, y1, x2, y2, color, true);
    }
}

void draw_clock_init(void )
{
	gui_draw_wide_line(55, 250, 80, 210, GREEN, 50);
	draw_line(55, 300, 10, 242, GREEN);
	draw_circle(55, 250, 30, RED);
	draw_fill_circle(55+30+35, 250, 30, RED);
	draw_round_rec(160, 205, 190, 205+30, 10, BLUE);
	draw_fill_round_rec(195, 205, 225, 205+60, 10, BLUE);
	
	draw_circle(100, 100, 100, RED);
	
	draw_arc(170, 280, 20, 1|2|4|8, WHITE);
	
	draw_clock_ticks(100,100,100,RED);
}

void draw_clock(void )
{
	int16_t second_hand_length = 80;
    int16_t minute_hand_length = 70;
    int16_t hour_hand_length = 60;
	
	int second = 0, minute = 20, hour = 1;
	int16_t xc = 100, yc=100;
	
	float prev_second_angle = 0.0f, prev_minute_angle = 0.0f, prev_hour_angle = 0.0f;
	
	static float second_angle, minute_angle, hour_angle;
	
	//计算初始角度
	second_angle = (float)(second * 6) - 90;  // Each second corresponds to 6 degrees
    minute_angle = (float)(minute * 6 + second / 10) - 90;  // Each minute is 6 degrees, plus 0.1 degree per second
    hour_angle = (float)(hour * 30 + minute / 2) - 90;  // Each hour is 30 degrees, plus 0.5 degree per minute
	
	prev_hour_angle = hour_angle;
	prev_minute_angle = minute_angle;
	prev_second_angle = second_angle;
	
	while (1) {
		// Calculate angles
        second_angle = (float)(second * 6) - 90;  // Each second corresponds to 6 degrees
		
		if (second % 30 == 0) {
			draw_hand(xc, yc, prev_minute_angle, minute_hand_length, BLACK);
			minute_angle = (float)(minute * 6 + second / 10) - 90;  // Each minute is 6 degrees, plus 0.1 degree per second
			prev_minute_angle = minute_angle;
		}
		
		if (minute % 6 == 0 && second == 0) {
			draw_hand(xc, yc, prev_hour_angle, hour_hand_length, BLACK);
			hour_angle = (float)(hour * 30 + minute / 2) - 90;  // Each hour is 30 degrees, plus 0.5 degree per minute
			prev_hour_angle = hour_angle;
		}
		
        draw_hand(xc, yc, prev_second_angle, second_hand_length, BLACK);

        // Draw new hands
        draw_hand(xc, yc, second_angle, second_hand_length, GREEN);
        draw_hand(xc, yc, minute_angle, minute_hand_length, GREEN);
        draw_hand(xc, yc, hour_angle, hour_hand_length, GREEN);
		draw_fill_circle(xc, yc, 4, GREEN);

		prev_second_angle = second_angle;
     
		delay_ms(1000);
		
		if (++second >= 60) {
			second = 0;
			if (++minute >= 60) {
				minute = 0;
				if (++hour >= 24) {
					hour = 0;
				}
			}
		}
	}
}

